package cn.myframe.utils;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.zip.CRC32;

public class MisUtil {
	
	/**
	 * 计算数据字节内容的总和
	 * @param data：要计算总和的数据
	 * @return：数据有效，返回计算出的总和；否在反回0
	 */
	public static long getDataSum(byte[] data){
		long res = 0;
		if(data != null){
			long value = 0;
			for (int i = 0; i < data.length; i++) {
				value = data[i]&0xFF;
				res += value;
			}
		}
		return res;
	}
	
	/**
	 * 获取类所在的应用程序运行时所在的路径
	 * @param cls
	 * @return
	 */
	public static String getAppPath(Class cls) {
		ClassLoader loader = cls.getClassLoader();
		String clsName = cls.getName() + ".class";
		Package pack = cls.getPackage();
		String path = "";
		if (pack != null) {
			String packName = pack.getName();
			clsName = clsName.substring(packName.length() + 1);
			if (packName.indexOf(".") < 0)
				path = packName + "/";
			else {
				int start = 0, end = 0;
				end = packName.indexOf(".");
				while (end != -1) {
					path = path + packName.substring(start, end) + "/";
					start = end + 1;
					end = packName.indexOf(".", start);
				}
				path = path + packName.substring(start) + "/";
			}
		}
		java.net.URL url = loader.getResource(path + clsName);
		String realPath = url.getPath();
		int pos = realPath.indexOf("file:");
		if (pos > -1){
			realPath = realPath.substring(pos + 5);
		}

		pos = realPath.indexOf(path + clsName);
		realPath = realPath.substring(0, pos - 5);
		if (realPath.endsWith("!"))
			realPath = realPath.substring(0, realPath.lastIndexOf("/"));
		return realPath;
	}
	
	public static boolean isJpeg(byte[] data){
		boolean res = false;
		if(data != null && data.length > 4){
			if((data[0]&0xFF) == 0xFF && (data[1]&0xFF)==0xD8 && (data[data.length-2]&0xFF)==0xFF && (data[data.length-1]&0xFF)==0xD9){
				res = true;
			}
		}
		return res;
	}
	
	public static int getInt(String src){
		int res = -1;
		try {
			res = Integer.parseInt(src);			
		}
		catch (RuntimeException e) {
			res = -1;
		}
		return res;
	}
	
	public static String StringAllReplace(String source, String oldstr, String newstr){
		String str = "";
		if (source == null || oldstr == null || newstr == null){
			return source;
		}
		//Logger.debug("Replace source string: "+source);
		int index = 0, start = 0;
		while(true){
			start = source.indexOf(oldstr, index);
			if (start < 0 || start >= source.length() || start+oldstr.length() > source.length()){
				break;
			}
			if (start > index){
				str += source.subSequence(index, start);
			}
			str += newstr;
			index = start+oldstr.length();
			start = source.indexOf(oldstr, index);
		}
		if (index == 0){
			str = source;
		}else{
			str += source.substring(index);
		}
//		Logger.debug("Replace new string: "+str);
		return str;
	}
	
	public static String StringReplace(String source, String oldstr, String newstr){
		String str = "";
		if (source == null || oldstr == null || newstr == null){
			return source;
		}
//		Logger.debug("Replace source string: "+source);
//		Logger.debug("Replace substr: "+oldstr+" with new substr: "+newstr);
		int start = source.indexOf(oldstr);
//		Logger.debug("Replace source string len: "+source.length()+", start ="+start);
		if (start < 0 || start >= source.length() || start+oldstr.length() > source.length()){
			return source;
		}
		String str1 = source.substring(0, start);
		String str2 = source.substring(start+oldstr.length());
		str = str1 +newstr+ str2;
//		Logger.debug("Replace new string: "+str);
		return str;
	}
		
	public static String[] StringSplit(String source,char spliter){
		List list = new ArrayList();
		String sub;
		String[] result;
		if (source.charAt(0) == spliter)
			source = source.substring(1, source.length());
		if (source.charAt(source.length() - 1) == spliter)
			source = source.substring(0, source.length() - 1);
		int start = 0;
		int end = source.indexOf(spliter);
		while (end > 0) {
			sub = source.substring(start, end);
			list.add(sub);
			start = end + 1;
			end = source.indexOf(spliter, start);
		}
		sub = source.substring(start, source.length());
		list.add(sub);
		result = new String[list.size()];
		Iterator iter = list.iterator();
		int i = 0;
		while (iter.hasNext()) {
			result[i++] = (String) iter.next();
		}
		return result;
	}
	
	/**
	 * 把任意字符串按照每行最大字符数进行拆分，中文按照2个字符计算
	 * @param mOrigianlString：原始内容，可能是中英文混合内容
	 * @param subStringCharNumber：拆分时每行最大的字符个数
	 * @return：拆分后的每行内容的集合
	 */
	public static ArrayList GetSeparateSubString(String mOrigianlString, int subStringCharNumber) {
		ArrayList resultList = new ArrayList(); 
		String tempStr = mOrigianlString; 
		int charNumber = subStringCharNumber; 
		int totalCount = 0; 
		String mSubStr = ""; 
		for (int i = 0; i < tempStr.length(); i++) { 
			String mChar = tempStr.substring(i, i+1); 
			int byteCount = mChar.getBytes().length;
			//关键点判断字符所占的字节数 
			if (byteCount == 1) { 
				totalCount++; 
				mSubStr += mChar; 
				if (totalCount == charNumber || i == tempStr.length() - 1) { 
					resultList.add(mSubStr); 
					totalCount = 0; 
					mSubStr = ""; 
				} 
			} 
			else if (byteCount > 1) { 
				totalCount += 2; 
				if (totalCount > charNumber ) { 
					resultList.add(mSubStr); 
					if (i == tempStr.length() - 1) { 
						mSubStr = mChar; 
						resultList.add(mSubStr); 
					} 
					else { 
						totalCount = 2; 
						mSubStr = mChar; 
					} 
				} 
				else if (totalCount == charNumber) { 
					mSubStr += mChar; 
					resultList.add(mSubStr); 
					totalCount = 0; 
					mSubStr = ""; 
				} 
				else if (i == tempStr.length() - 1) { 
					mSubStr += mChar; 
					resultList.add(mSubStr); 
				} 
				else { 
					mSubStr += mChar; 
				} 
			} 
		} 
		return resultList; 
	} 

	// 将MJD格式的时间转换为秒，取5个字节的数据进行换算
	public static long byteMjdToMillis(byte[] data, int curp) {
		if (data == null) {
			throw new IllegalArgumentException("byte array is null!");
		}
//		Logger.debug("byteMjdToMillis data: "+data[curp+0]+","+data[curp+1]+","+data[curp+2]+","+data[curp+3]+","+data[curp+4]+"");
		//取2个字节数据作为年月日
		int i = byteToShort(data, curp)&0xffff;
		//分别获取年月日
		int y = mjdTOymdY(i);
		int m = mjdTOymdM(i);
		int d = mjdTOymdD(i);
		//分别获取时分秒
		int hour = data[curp + 2]&0xff;//(data[curp + 2] >> 4) * 10 + (data[curp + 2] & 0x0F);
		int minute = data[curp + 3]&0xff;//(data[curp + 3] >> 4) * 10 + (data[curp + 3] & 0x0F);
		int second = data[curp + 4]&0xff;//(data[curp + 4] >> 4) * 10 + (data[curp + 4] & 0x0F);
		if (hour == 0xff && minute== 0xff && second == 0xff){
			return 0xffffffff;
		}
		//构建Calendar
		Calendar c = Calendar.getInstance();
		if (c == null){
			return 0;
		}
		c.set(y, m - 1, d, hour, minute, second);
		
		return c.getTimeInMillis();
	}

	// 将BCD格式的时间转换为毫秒，取3个字节的数据进行换算
	public static long byteBcdToMills(byte[] data, int curp) {
		if (data == null) {
			throw new IllegalArgumentException("byte array is null!");
		}
		//分别获取时分秒
		int hour = data[curp + 0]&0xff;//(data[curp + 2] >> 4) * 10 + (data[curp + 2] & 0x0F);
		int minute = data[curp + 1]&0xff;//(data[curp + 3] >> 4) * 10 + (data[curp + 3] & 0x0F);
		int second = data[curp + 2]&0xff;//(data[curp + 4] >> 4) * 10 + (data[curp + 4] & 0x0F);
		if (hour == 0xff && minute== 0xff && second == 0xff){
			return 0xffffffff;
		}
		return hour*3600 + minute*60 + second;
	}
	
	public static int byteToShort(byte[] data, int curp) {
//		if (data == null) {
//			throw new IllegalArgumentException("byte array is null!");
//		}
		int r = 0;
		for (int i = 0; i < 2; i++) {
			r <<= 8;
			if (data[curp] > 0){
				r |= (data[curp] & 0x00ff);
			}
			else{
				r |= ((data[curp]+256) & 0x00ff);
			}
			curp++;
		}
		return r;
	}

	public static int byteToInt(byte[] data, int curp) {
//		if (data == null) {
//			throw new IllegalArgumentException("byte array is null!");
//		}
		int r = 0;
		for (int i = 0; i < 4; i++) {
			r <<= 8;
			if (data[curp] > 0){
				r |= (data[curp] & 0x000000ff);
			}
			else{
				r |= ((data[curp]+256) & 0x000000ff);
			}
			curp++;
		}
		return r;
	}
	
	public static int byte3ToInt(byte[] data, int curp) {
//		if (data == null) {
//			throw new IllegalArgumentException("byte array is null!");
//		}
		int r = 0;
		for (int i = 0; i < 3; i++) {
			r <<= 8;
			if (data[curp] > 0){
				r |= (data[curp] & 0x000000ff);
			}
			else{
				r |= ((data[curp]+256) & 0x000000ff);
			}
			curp++;
		}
		return r;
	}
	
	public static long byteToLong(byte[] data, int curp) {
		if (data == null) {
			throw new IllegalArgumentException("byte array is null!");
		}
		long r = 0;
		for (int i = 0; i < 4; i++) {
			if (data[curp] > 0){
				r |= (data[curp] & 0x000000ff);
			}
			else{
				r |= ((data[curp]+256) & 0x000000ff);
			}
			curp++;
		}
		return r;
	}

	public static void shortToByte(byte buff[], int curp, short value) {
		if (buff == null) {
			throw new IllegalArgumentException("byte array is null!");
		}
		int idx = curp+1;
		for (int i = 0; i < 2; i++) {
			buff[idx--] = (byte) (value & 0x00ff);
			value >>= 8;
		}
	}

	public static void intToByte(byte buff[], int curp, int value) {
		if (buff == null) {
			throw new IllegalArgumentException("byte array is null!");
		}
		int idx = curp+3;
		for (int i = 0; i < 4; i++) {
			buff[idx--] = (byte) (value & 0x000000ff);
			value >>= 8;

		}
	}
	//非典型数据转换 modify by hzm @2011-8-18
	public static long byte8ToLong(byte[] buff, int len) {
		if (buff == null) {
			throw new IllegalArgumentException("byte array is null!");
		}
		long r = 0;
		for (int i = 0; i < 8; i++) {
			r <<= 4;
			r |= (buff[len++] & 0x00000000000000ff);
		}
		return r;
	}

	// 指定数组清0
	public static void clearString(byte[] buff, int len) {
		if (buff != null){
		for (int i = 0; i < len; i++) {
			buff[i] = (byte) 0;
			}
		}
	}
	
	public static int str2Int(String str){
		if (str == null){
			return 0;
		}
		try {
			return Integer.parseInt(str);
		} catch (Exception e) {
			// TODO: handle exception
			return 0;
		}
	}

	// 字符转数字
	public static byte char2Number(byte code) {
		byte ret = 0;
		if (code >= '0' && code <= '9') {
			ret = (byte) (code - 48);
		} else if (code >= 'a' && code <= 'f') {
			ret = (byte) (code - 87);
		} else if (code >= 'A' && code <= 'F') {
			ret = (byte) (code - 55);
		} else {
			ret = 0;
		}
		return ret;
	}

	public static long convertCANoToHex(byte[] cardid, int num) {
		byte[] card = new byte[8];
		int cut = 0, i = 0;
		long value = 0;
		if ((cardid == null) || (num == 0)) {
			card = null;
			return 0;
		}
		clearString(card, 8);
		if (num > 8) {

			// 8位以后截断
			cut = num - 8;
		} else {
			cut = 0;
		}
		for (i = num - 1; i >= cut; i--) {
			card[i] = char2Number(cardid[i]);
		}
		value = byte8ToLong(card, 0);
		card = null;
		return value;
	}

	public static long pow(long x, char n) {
		long value = 1;
		for (; n > 0; n--) {
			value *= x;
		}
		return value;
	}

	// 20100902
	public static long convertCANoToDec(byte[] cardid, int num) {
		byte[] card = new byte[10];
		long value = 0;
		int i = 0;
		char j = 0;
		if ((cardid == null) || (num > 10)) {
			card = null;
			return 0;
		}
		clearString(card, 8);
		for (i = num - 1; i >= 0; i--) {
			card[num - 1 - i] = char2Number(cardid[i]);
		}
		for (j = 0; j < 10; j++) {
			if (card[j] > 9) {
				return 0;
			} else {
				value += card[j] * pow(10, j);
			}
		}
		card = null;
		return value;
	}
	
	//计算天数差
	public static int daysBetween(String sEndDate) {
		int days = 0;
		Calendar calendar1=Calendar.getInstance();
		Calendar calendar2=Calendar.getInstance();
		try{
			SimpleDateFormat formatter1 = new SimpleDateFormat("yyyyMMdd");
			calendar1.setTime(formatter1.parse(formatter1.format(new Date())));
			calendar2.setTime(formatter1.parse(sEndDate));
			days =  (int)( (calendar2.getTimeInMillis()-calendar1.getTimeInMillis())/1000/60/60/24);
		}catch(Exception e){
			
		}
		return days;
	}

	// 将字符转成大写
	public static byte changeCapital(byte code) {
		byte capital = code;
		if (capital >= 'a' && capital <= 'z'){
			capital = (byte)(capital - 32);
		}
		if (capital>'z'){
			capital = 0;
		}
		return capital;
	}

	static private int[] table = {
		0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b,
		0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61,
		0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd, 0x4c11db70, 0x48d0c6c7,
		0x4593e01e, 0x4152fda9, 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75,
		0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3,
		0x709f7b7a, 0x745e66cd, 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
		0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 0xbe2b5b58, 0xbaea46ef,
		0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d,
		0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49, 0xc7361b4c, 0xc3f706fb,
		0xceb42022, 0xca753d95, 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1,
		0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 0x34867077, 0x30476dc0,
		0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072,
		0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, 0x018aeb13, 0x054bf6a4,
		0x0808d07d, 0x0cc9cdca, 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde,
		0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02, 0x5e9f46bf, 0x5a5e5b08,
		0x571d7dd1, 0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
		0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b, 0xbb60adfc,
		0xb6238b25, 0xb2e29692, 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6,
		0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a, 0xe0b41de7, 0xe4750050,
		0xe9362689, 0xedf73b3e, 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2,
		0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34,
		0xdc3abded, 0xd8fba05a, 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637,
		0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb, 0x4f040d56, 0x4bc510e1,
		0x46863638, 0x42472b8f, 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53,
		0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5,
		0x3f9b762c, 0x3b5a6b9b, 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
		0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 0xf12f560e, 0xf5ee4bb9,
		0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b,
		0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f, 0xc423cd6a, 0xc0e2d0dd,
		0xcda1f604, 0xc960ebb3, 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7,
		0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 0x9b3660c6, 0x9ff77d71,
		0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3,
		0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, 0x4e8ee645, 0x4a4ffbf2,
		0x470cdd2b, 0x43cdc09c, 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8,
		0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24, 0x119b4be9, 0x155a565e,
		0x18197087, 0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
		0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d, 0x2056cd3a,
		0x2d15ebe3, 0x29d4f654, 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0,
		0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c, 0xe3a1cbc1, 0xe760d676,
		0xea23f0af, 0xeee2ed18, 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4,
		0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662,
		0x933eb0bb, 0x97ffad0c, 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668,
		0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4};

	public static long getCRC32(byte[] buff, int start, int len) {
		long res = 0;
		if (buff == null){
			return 0;
		}
		int crc32 = 0xffffffff;
        for (int i = 0; i < len; i++) { 
        	crc32 = ((crc32 <<8) ^ (table[((((int)(crc32>>24)) ^ (buff[start+i])) & 0xff)])); 
        }    
        res = crc32;
		return res;
	}
	
	public static long getCRC32ByFile(File file){
		try{
			    byte[] buff = null;  
			    FileInputStream fis = new FileInputStream(file);  
	            ByteArrayOutputStream bos = new ByteArrayOutputStream();  
	            byte[] b = new byte[1024];  
	            int n;  
	            while ((n = fis.read(b)) != -1)  
	            {  
	                bos.write(b, 0, n);  
	            }  
	            fis.close();  
	            bos.close();  
	            buff = bos.toByteArray();
	            int start=0;
	            int len=buff.length;
	            long res = 0;
	    		if (buff == null){
	    			return 0;
	    		}
	    		int crc32 = 0xffffffff;
	            for (int i = 0; i < len; i++) { 
	            	crc32 = ((crc32 <<8) ^ (table[((((int)(crc32>>24)) ^ (buff[start+i])) & 0xff)])); 
	            }    
	            res = crc32;
	    		return res;
			
		}catch(Exception e){
			e.printStackTrace();
		}
		return 0;
	}
	
	public static byte[] mallocEtvBuff(int size) {
		if(size <= 0)
			return null;
		byte[] res = null;
		try {
			res = new byte[size];
		}
		catch (RuntimeException e) {
			res = null;
			return null;
		}
		clearString(res,size);
		return res;
	}

	public static int bcd2Oct(int bcdData) {
		int octData = ((bcdData & 0x0000000F) + ((bcdData & 0x000000F0) >> 4)
				* 10 + ((bcdData & 0x00000F00) >> 8) * 100
				+ ((bcdData & 0x0000F000) >> 12) * 1000
				+ ((bcdData & 0x000F0000) >> 16) * 10000
				+ ((bcdData & 0x00F00000) >> 20) * 100000
				+ ((bcdData & 0x0F000000) >> 24) * 1000000 + (bcdData >> 28) * 10000000) / 10;

		return octData;
	}

	// MJD to Y
	private static int mjdTOymdY(int i) {
		int j = (int) (((double) i - 15078.200000000001D) / 365.25D);
		int k = (int) (((double) i - 14956.1D - (double) (int) ((double) j * 365.25D)) / 30.600100000000001D);
		int i1;
		if (k == 14 || k == 15) {
			i1 = 1;
		} else {
			i1 = 0;
		}
		int j1 = j + i1 + 1900;
		return j1;
	}

	// MJD to M
	private static int mjdTOymdM(int i) {
		int j = (int) (((double) i - 15078.200000000001D) / 365.25D);
		int k = (int) (((double) i - 14956.1D - (double) (int) ((double) j * 365.25D)) / 30.600100000000001D);
		int i1;
		if (k == 14 || k == 15) {
			i1 = 1;
		} else {
			i1 = 0;
		}
		int k1 = k - 1 - i1 * 12;
		return k1;
	}

	// MJD to D
	private static int mjdTOymdD(int i) {
		int j = (int) (((double) i - 15078.200000000001D) / 365.25D);
		int k = (int) (((double) i - 14956.1D - (double) (int) ((double) j * 365.25D)) / 30.600100000000001D);
		int l = i - 14956 - (int) ((double) j * 365.25D)
				- (int) ((double) k * 30.600100000000001D);
		return l;
	}
	
	public static String getCrc32(String content){
		CRC32 crc32 = new CRC32();
		crc32.update(content.getBytes());
		Long value = crc32.getValue();
		return Long.toHexString(value);
	}
	public static long getLongCrc32(String content){
		CRC32 crc32 = new CRC32();
		crc32.update(content.getBytes());
		Long value = crc32.getValue();
		return value;
	}
}
